/*
 * COAPI - Copyright (C) 2019-2020 Cocheer Tech. Co., Ltd.
 * All rights reserved
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "coapi_dev_ctrl.h"

#include "coapi_devctrl.h"
#include "coapi_devsta.h"
#include "coapi_sync.h"
#include "coapi_dev.h"
#include "coapi_ota.h"
#include "coapi_logger.h"

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#include <aos/aos.h>
#include <smart_audio.h>

#define MAX_VOLUME (100)
#define MIN_VOLUME (0)

static void dev_volume_up_ctrl(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    smtaudio_vol_up(10);
}

static void dev_volume_down_ctrl(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    smtaudio_vol_down(10);
}

static void dev_volume_val_ctrl(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    int volume = dp_bytes_to_int((const unsigned char *)data);

    smtaudio_vol_set(volume);
}

static void dev_volume_mute_ctrl(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    dev_mute();
}

static void dev_volume_max_ctrl(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    smtaudio_vol_set(MAX_VOLUME);
}

static void dev_volume_min_ctrl(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    smtaudio_vol_set(MIN_VOLUME);
}

static void dev_volume_unmute_ctrl(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    dev_unmute();
}

static void dev_ota_start_ctrl(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    dev_ota_start();
}

static void dev_ota_cancle_ctrl(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    dev_ota_cancle();
}

static void dev_childlock_ctrl(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    int state = dp_bytes_to_int((const unsigned char *)data);
    if (state == CHILDLOCK_OPEN) {
        dev_childlock_open();
    } else if (state == CHILDLOCK_CLOSE) {
        dev_childlock_close();
    } else {
        /* 云端给设备端设置状态 */
        int status = dev_childlock_status();
        coapi_devsta_int(NULL,NULL,DEV_CHILDLOCK, 0, status);
    }
}

static void dev_on_ctrl(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    dev_power_onoff();
}

static void dev_off_ctrl(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    dev_power_onoff();
}

static void dev_reboot_ctrl(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    dev_restart();
}

static void warmer_on(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
  	xdebug("===warmer_on=== dpid: %d  len: %d =====",dpid, len);
}

static void warmer_off(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    xdebug("===warmer_off===== dpid: %d  len: %d =====",dpid, len);
}

static void warmer_value(char *appkey, char *devid,int dpid,char *data, int len, int opt)
{
    xdebug("=====warmer_value====== dpid: %d len: %d ", dpid, len);

	int value = dp_bytes_to_int((const unsigned char *)data);
	xdebug("value: %d ", value);
	
}



static const devctrl_dps_t handles[] = {
    {DEV_VOLUME_UP,     DEV_TYPE_INT, dev_volume_up_ctrl, NULL,NULL},
    {DEV_VOLUME_DOWN,   DEV_TYPE_INT, dev_volume_down_ctrl,NULL,NULL},
    {DEV_VOLUME_VAL,    DEV_TYPE_INT, dev_volume_val_ctrl,NULL,NULL},
    {DEV_VOLUME_MUTE,   DEV_TYPE_INT, dev_volume_mute_ctrl,NULL,NULL},
    {DEV_VOLUME_MAX,    DEV_TYPE_INT, dev_volume_max_ctrl,NULL,NULL},
    {DEV_VOLUME_MIN,    DEV_TYPE_INT, dev_volume_min_ctrl,NULL,NULL},
    {DEV_VOLUME_UNMUTE, DEV_TYPE_INT, dev_volume_unmute_ctrl,NULL,NULL},

    {DEV_OTA_START,     DEV_TYPE_INT, dev_ota_start_ctrl,NULL,NULL},
    {DEV_OTA_CANCEL,    DEV_TYPE_INT, dev_ota_cancle_ctrl,NULL,NULL},

    {DEV_CHILDLOCK,     DEV_TYPE_INT, dev_childlock_ctrl,NULL,NULL},

    {DEV_ON,            DEV_TYPE_INT, dev_on_ctrl,NULL,NULL},
    {DEV_OFF,           DEV_TYPE_INT, dev_off_ctrl,NULL,NULL},
    {DEV_REBOOT,        DEV_TYPE_INT, dev_reboot_ctrl,NULL,NULL},

	{WARMER_ON,         DEV_TYPE_INT, warmer_on,NULL,NULL},
    {WARMER_OFF,        DEV_TYPE_INT, warmer_off,NULL,NULL},
    {WARMER_VALUE,      DEV_TYPE_INT, warmer_value,NULL,NULL},
};

static void *dev_status_update_thread(void *arg)
{
    int exit = 0;
    int prev_volume = 0, curr_volume = 0;
    int prev_battery = 0, curr_battery = 0;
    int prev_charge = 0, curr_charge = 0;
    int prev_free = 0, curr_free = 0;
    int prev_childlock = 0, curr_childlock = 0;
    int prev_ota = 0, curr_ota = 0;
    int all = 0;

    /**
     * 获取存储总容量和剩余容量
     */
    dev_get_storage(&all, &curr_free);
    coapi_devsta_int(NULL,NULL,DEV_STORE_QUERY_TATOL, 0, all);                /* 向数据后台更新存储总容量 */
    coapi_devsta_int(NULL,NULL,DEV_STORE_QUERY_FREE, 0,  curr_free);          /* 向数据后台更新剩余容量 */
    coapi_devsta_int(NULL,NULL,DEV_STORE_QUERY_USED, 0,  all - curr_free);    /* 向数据后台更新使用容量 */

    while (!exit) {

        /**
         * 获取当前音量值,判断是否变化
         * 如果变化，更新至数据后台
         */
        curr_volume = smtaudio_vol_get();
        if (prev_volume != curr_volume) {
            coapi_devsta_int(NULL,NULL,DEV_VOLUME_VAL, 0, curr_volume);       /* 向数据后台更新音量 */
            if (curr_volume == MAX_VOLUME) {
                coapi_devsta_int(NULL,NULL,DEV_VOLUME_MAX, 0, curr_volume);   /* 向数据后台更新最大音量 */
            } else if (curr_volume == MIN_VOLUME) {
                coapi_devsta_int(NULL,NULL,DEV_VOLUME_MIN, 0, curr_volume);   /* 向数据后台更新最小音量 */
            }
        }
        prev_volume = curr_volume;

        /**
         * 获取当前电量值,判断是否变化
         * 如果变化，更新至数据后台
         */
        curr_battery = dev_get_battery();
        if (prev_battery != curr_battery) {
            coapi_devsta_int(NULL,NULL,DEV_BATTERY_CHECK, 0, curr_battery); /* 向数据后台更新电量值 */
        }
        prev_battery = curr_battery;

        /**
         * 获取充电状态,判断是否变化
         * 如果变化，更新至数据后台
         */
        curr_charge = dev_get_charge();
        if (prev_charge != curr_charge) {
            coapi_devsta_int(NULL,NULL,DEV_CHARGE_CHECK, 0, curr_charge);  /* 向数据后台更新充电状态 */
        }
        prev_charge = curr_charge;

        /**
         * 获取当前剩余容量,判断是否变化
         * 如果变化，更新至数据后台
         */
        dev_get_storage(&all, &curr_free);
        if (prev_free != curr_free) {
            coapi_devsta_int(NULL,NULL,DEV_STORE_QUERY_FREE, 0,  curr_free);          /* 向数据后台更新剩余容量 */
            coapi_devsta_int(NULL,NULL,DEV_STORE_QUERY_USED, 0,  all - curr_free);    /* 向数据后台更新使用容量 */
        }
        prev_free = curr_free;

        /**
         * 获取当前童锁状态,判断是否变化
         * 如果变化，更新至数据后台
         */
        curr_childlock = dev_childlock_status();
        if (prev_childlock != curr_childlock) {
            coapi_devsta_int(NULL,NULL,DEV_CHILDLOCK, 0, curr_childlock);  /* 向数据后台更新童锁状态 */
        }
        prev_childlock = curr_childlock;

        /**
         * 获取ota状态,判断是否变化
         * 如果变化，更新至数据后台
         */
        curr_ota = dev_ota_status();
        if (prev_ota != curr_ota) {
            switch (curr_ota) {
                case OTA_SUCCESS:
                    coapi_devsta_int(NULL,NULL,DEV_OTA_SUCCESS, 0, curr_ota);         /* 向数据后台更新ota成功 */
                    break;
                case OTA_FAIL:
                    coapi_devsta_int(NULL,NULL,DEV_OTA_FAIL, 0, curr_ota);            /* 向数据后台更新ota失败 */
                    break;
                case OTA_NONE:
                    break;
                default:
                    if (curr_ota > 0 && curr_ota <= 100) {
                        coapi_devsta_int(NULL,NULL,DEV_OTA_PROGRESS, 0, curr_ota);    /* 向数据后台更新ota进度 */
					}
                break;
            }
        }
        prev_ota = curr_ota;

        aos_msleep(10000);  /*轮询时间可以适当调整,默认10s查询一次*/
    }
	return NULL;
}

/**
 * @brief 数据点上报结果回调接口
 * @param dpid 
 *        - success 对应的数据点ID
 *        - fail 错误码
   @param data reserve
 * @return void
 *
 */
void devsta_resp(int dpid,char *data)
{

}

int coapi_dev_ctrl_init(void)
{
    pthread_t tid = 0;

	/**
	 * 设备控制数据点下发初始化
	 */
    coapi_devctrl_init((devctrl_dps_t *)handles, sizeof(handles)/sizeof(handles[0]));

	/**
	 * 设备数据点上报初始化接口
	 */
	coapi_devsta_init(devsta_resp);

	/**
	 * 创建数据点上报线程
	 */
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    int ret = pthread_create(&tid, &attr, dev_status_update_thread, NULL);
    if (ret == -1) {
        printf("create ai feed thead failed\n");
        return -1;
    }
	
    return 0;
}

int coapi_dev_ctrl_deinit(void)
{
	coapi_devsta_deinit();
	coapi_devctrl_deinit();
	
	return 0;
}

